﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ProjectController.cs" company="">
//   Copyright (c) 2010/2011 All Right Reserved
// </copyright>
// <summary>
//   Contains ProjectController class declaration.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace IBupro.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;

    using IBupro.Controllers.Classes;
    using IBupro.Models;

    using iBuproModel;
    using iBuproModel.Repositories.Interfaces;

    /// <summary>
    /// This controller contains actions related to project.
    /// </summary>
    [HandleError]
    public class ProjectController : CustomController
    {
        private IProjectRepository projectRepository;

        public ProjectController() 
        {
            this.projectRepository = repositoryService.ProjectRepositoryCreateInstance();
        }
        
        public ActionResult Index()
        {
            return View(projectRepository.GetAll());
        }

        public ActionResult Filter(int id)
        {
            try
            {
                return View(projectRepository.GetProjectsForSubject(id));
            }
            catch
            {

                throw new Exception("Cannot filter projects by subject");
            }
        }

        public ActionResult Details(int id)
        {
            try
            {
                Project project = projectRepository.GetSingle(x => x.Id == id);

                return View(project) ;
            }
            catch
            {
                throw new Exception("Cannot display requested project.");
            }
        }

        [Authorize(Roles = "Student, Lector")]
        public ActionResult Create()
        {
            try
            {
                Entities context = new Entities();
                ViewData["Categories"] = new SelectList(context.Subjects.ToList(), "Id", "Name");
                return View();   
            }
            catch
            {
                throw new Exception("Cannot create project");
            }
        } 

        [HttpPost]
        [Authorize(Roles = "Student, Lector")]
        public ActionResult Create(ProjectModel project)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    Entities context = new Entities();
                    Project newProject = new Project();

                    newProject.Name = project.Name;
                    newProject.Created = DateTime.Now;
                    newProject.Detail = project.Detail;
                    newProject.Shortcut = project.Shortcut;
                    newProject.Subject  = context.Subjects.Where(s => s.Id == project.SubjectId).SingleOrDefault();

                    User thisUser = context.Users.Where(u => u.Username == User.Identity.Name).SingleOrDefault();
                    thisUser.Projects.Add(newProject);
                    thisUser.LectorProjects.Add(newProject);

                    context.SaveChanges();
                }
                else
                {
                    return View(project);
                }

                return RedirectToAction("Index", "Student");
            }
            catch
            {
                throw new Exception("Cannot create project");
            }
        }

        [Authorize(Roles = "Student")]
        public ActionResult Edit(int id)
        {
            try
            {
                Project project = this.projectRepository.GetSingle(x => x.Id == id);

                return View(project);
            }
            catch
            {
                throw new Exception("Cannot display requested project.");
            }
        }

        [Authorize(Roles = "Student")]
        [HttpPost]
        public ActionResult Edit(Project project)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    var oldProject = this.projectRepository.First(x => x.Id == project.Id);

                    oldProject.Name = project.Name;
                    oldProject.Detail = project.Detail;
                    oldProject.Shortcut = project.Shortcut;
                    oldProject.Approved = project.Approved;

                    this.projectRepository.SaveChanges();
                }
                else
                {
                    return View(project);
                }

                return RedirectToAction("Index");
            }
            catch (Exception e)
            {
                throw new Exception("Cannot edit project");
            }
        }
        [Authorize(Roles = "Student")]
        public ActionResult Delete(int id)
        {
            return View();
        }

        [Authorize(Roles = "Student")]
        [HttpPost]
        public ActionResult Delete(int id, FormCollection collection)
        {
            try
            {
                // TODO: Add delete logic here
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        [Authorize(Roles = "Student")]
        public ActionResult Join(int id)
        {
            try
            {
                var context = new Entities();
                
                bool isAlreadyIn = context.Users.Where(u => u.Username == User.Identity.Name).SingleOrDefault().LectorProjects.Contains(context.Projects.Where(p => p.Id == id).SingleOrDefault());
                if (isAlreadyIn == false)
                {
                    return View();
                }
                else
                {
                    return RedirectToAction(
                        "Notify", "Project", new { message = "You are already added to this project." });
                }
            }
            catch
            {
                throw new Exception("Cannot join to project");
            }
        }

        [Authorize(Roles = "Student")]
        [HttpPost]
        public ActionResult Join(int id, FormCollection form)
        {
            try
            {
                var context = new Entities();
                var request = new OwnerRequest
                    {
                        Pending = true,
                        Text = form["Text"],
                        Project = context.Projects.Where(p => p.Id == id).SingleOrDefault(),
                        User = context.Users.Where(u => u.Username == this.User.Identity.Name).SingleOrDefault()
                    };

                context.OwnerRequests.AddObject(request);
                context.SaveChanges();

                return RedirectToAction("RequestSent");
            }
            catch
            {
                throw new Exception("Cannot join to project");
            }
        }

        [Authorize(Roles = "Student")]
        public ActionResult RequestSent()
        {
            return View();
        }

        [Authorize(Roles = "Student")]
        public ActionResult Requests()
        {
            try
            {
                var context = new Entities();
                /*var req = from r in context.OwnerRequests
                          join p in context.Projects on r.Project.Id equals p.pri*/

                User user = context.Users.Where(u => u.Username == User.Identity.Name).SingleOrDefault();

                List<Project> projects = user.LectorProjects.ToList();

                List<OwnerRequest> requests = new List<OwnerRequest>();

                foreach (Project p in projects.ToList())
                {
                    foreach (OwnerRequest request in p.OwnerRequests.Where(r => r.Pending == true))
                    {
                        requests.Add(request);
                    }
                }
                
                return View(requests);
            }
            catch
            {
                throw new Exception("Cannot get requests");
            }
        }

        [Authorize(Roles = "Student")]
        public ActionResult RequestDetail(int id)
        {
            try
            {
               var context = new Entities();
               
                return View(context.OwnerRequests.Where(r => r.Id == id && r.Pending == true).SingleOrDefault());
            }
            catch
            {
                throw new Exception("Cannot get request detail");
            }
        }

        [Authorize(Roles = "Student")]
        public ActionResult RequestAccept(int id)
        {
            try
            {
                var context = new Entities();

                OwnerRequest request =
                    context.OwnerRequests.Where(r => r.Id == id && r.Project.Principal.Username == User.Identity.Name).
                        SingleOrDefault();

                context.OwnerRequests.Where(r => r.Id == request.Id).SingleOrDefault().Pending = false;

                Project project = request.Project;
                context.Projects.Where(p => p.Id == project.Id).SingleOrDefault().Users.Attach(request.User);

                context.SaveChanges();

                return RedirectToAction("Notify", "Project", new { message = "Request has been accepted" });
            }
            catch
            {
                throw new Exception("Cannot accept request");
            }
        }

        [Authorize(Roles = "Student")]
        public ActionResult RequestCancel(int id)
        {
           try
            {
                var context = new Entities();

                OwnerRequest request = context.OwnerRequests.Where(r => r.Id == id && r.Project.Principal.Username == User.Identity.Name).SingleOrDefault();

                context.OwnerRequests.Where(r => r.Id == request.Id).SingleOrDefault().Pending = false;

                context.SaveChanges();

                return RedirectToAction("Notify", "Project", new { message = "Request has been canceled" });
            }
            catch
            {
                throw new Exception("Cannot accept request");
            }
        }

        [Authorize(Roles = "Student")]
        public ActionResult Notify(string message)
        {
            ViewData["message"] = message;
            return View();
        }

        [Authorize(Roles = "Student")]
        public ActionResult Leave(int id)
        {
            try
            {
                var context = new Entities();

                User user = context.Users.Where(u => u.Username == User.Identity.Name).SingleOrDefault();
                Project project = context.Projects.Where(p => p.Id == id).SingleOrDefault();

                if (!user.Projects.Contains(project) && user.LectorProjects.Contains(project))
                {
                    return RedirectToAction("Notify", "Project", new { message = "You are not in involved in this project." });
                }

                user.Projects.Remove(project);

                context.SaveChanges();
                
                return RedirectToAction("Notify", "Project", new { message = "You have been removed from the project." });
            }
            catch
            {
                throw new Exception("Cannot leave project");
            }
        }

        [Authorize(Roles = "Student")]
        public ActionResult CreateSubProject(int id)
        {
            try
            {
                var context = new Entities();
                
                if (!context.Projects.Where(p => p.Id == id).SingleOrDefault().Approved)
                {
                    return RedirectToAction("Notify", "Project", new { message = "Project " + context.Projects.Where(p => p.Id == id).SingleOrDefault().Name + " must be approved firs!" });
                }

                ViewData["ParentProject"] = context.Projects.First(p => p.Id == id);
                ViewData["Subjects"] = new SelectList(context.Subjects.ToList(), "Id", "Name");
                return View();
            }
            catch
            {
                throw new Exception("Cannot create sub project");
            }
        }

        [Authorize(Roles = "Student")]
        [HttpPost]
        public ActionResult CreateSubProject(int id, ProjectModel project)
        {
            try
            {
                var context = new Entities();
                
                if (!context.Projects.Where(p => p.Id == id).SingleOrDefault().Approved)
                {
                    return RedirectToAction("Notify", "Project", new { message = "Project " + context.Projects.Where(p => p.Id == id).SingleOrDefault().Name + " must be approved firs!" });
                }

                if (ModelState.IsValid)
                {
                    var newProject = new Project();

                    newProject.Name = project.Name;
                    newProject.Created = DateTime.Now;
                    newProject.Detail = project.Detail;
                    newProject.Shortcut = project.Shortcut;
                    newProject.Subject = context.Subjects.Where(s => s.Id == project.SubjectId).SingleOrDefault();

                    User thisUser = context.Users.Where(u => u.Username == User.Identity.Name).SingleOrDefault();
                    thisUser.Projects.Add(newProject);
                    thisUser.LectorProjects.Add(newProject);

                    Project parentProject = context.Projects.Where(p => p.Id == id).SingleOrDefault();
                    parentProject.Projects.Add(newProject);

                    context.SaveChanges();

                }
                else
                {
                    return View(project);
                }

                return RedirectToAction("Index");
            }
            catch
            {
                throw new Exception("Cannot create sub project");
            }
        }
    }
}
